package com.xuecheng.user.service.impl;

import cn.hutool.core.util.StrUtil;
import com.xuecheng.api.client.CheckcodeClient;
import com.xuecheng.base.constant.RoleIdConstant;
import com.xuecheng.base.constant.UserTypeConstant;
import com.xuecheng.base.exception.CommonError;
import com.xuecheng.base.exception.XCPlusBaseException;
import com.xuecheng.user.exception.*;
import com.xuecheng.user.mapper.XcUserMapper;
import com.xuecheng.user.mapper.XcUserRoleMapper;
import com.xuecheng.user.model.dto.FindPasswordDTO;
import com.xuecheng.user.model.dto.RegisterUserDTO;
import com.xuecheng.user.model.po.XcUser;
import com.xuecheng.user.model.po.XcUserRole;
import com.xuecheng.user.service.IXcUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.UUID;

/**
 * <p>
 * user表 服务实现类
 * </p>
 *
 * @author 勾新杰
 * @since 2025-02-24
 */
@Service
@RequiredArgsConstructor
public class XcUserServiceImpl extends ServiceImpl<XcUserMapper, XcUser> implements IXcUserService {

    /**
     * 验证码服务
     */
    private final CheckcodeClient checkcodeClient;

    /**
     * 密码加密器
     */
    private final PasswordEncoder passwordEncoder;

    /**
     * 用户角色表
     */
    private final XcUserRoleMapper xcUserRoleMapper;

    /**
     * 找回密码
     *
     * @param findPasswordDTO 找回密码参数
     */
    @Override
    public void findPassword(FindPasswordDTO findPasswordDTO) {
        if (StrUtil.isBlank(findPasswordDTO.getCellphone()) && StrUtil.isBlank(findPasswordDTO.getEmail()))
            CellPhoneAndEmailCannotBothBeNullException.cast();
        // 1. 判断两次输入的密码是否相等
        String password = findPasswordDTO.getPassword();
        String confirmPassword = findPasswordDTO.getConfirmpwd();
        if (!password.equals(confirmPassword))
            AuthTwicePasswordNotMatchException.cast();
        // 2. 检查传入的验证码是否正确
        Boolean verify = checkcodeClient.verify(findPasswordDTO.getCheckcodekey(), findPasswordDTO.getCheckcode());
        if (!verify) AuthCheckCodeNotCorrectException.cast();
        // 3. 根据用户名和邮箱查询用户
        XcUser xcUser;
        if (!StrUtil.isBlank(findPasswordDTO.getCellphone())) {
            xcUser = lambdaQuery()
                    .eq(XcUser::getCellPhone, findPasswordDTO.getCellphone())
                    .one();
        } else {
            xcUser = lambdaQuery()
                    .eq(XcUser::getEmail, findPasswordDTO.getEmail())
                    .one();
        }
        if (xcUser == null) AuthUserNotExistException.cast();
        // 4. 修改密码
        xcUser.setPassword(passwordEncoder.encode(password));
        updateById(xcUser);
    }

    /**
     * 注册
     *
     * @param registerUserDTO 注册参数
     */
    @Override
    @Transactional
    public void register(RegisterUserDTO registerUserDTO) {
        // 1. 比较两次输入的密码是否一致
        if (!registerUserDTO.getPassword().equals(registerUserDTO.getConfirmpwd()))
            AuthTwicePasswordNotMatchException.cast();
        // 2. 检查验证码是否正确
        Boolean verify = checkcodeClient.verify(registerUserDTO.getCheckcodekey(), registerUserDTO.getCheckcode());
        if (!verify) AuthCheckCodeNotCorrectException.cast();
        // 3. 根据用户名查询用户，如果存在，则不允许注册
        XcUser xcUser = lambdaQuery().eq(XcUser::getUsername, registerUserDTO.getUsername()).one();
        if (xcUser != null) AuthUsernameAlreadyExistException.cast();
        xcUser = lambdaQuery().eq(XcUser::getEmail, registerUserDTO.getEmail()).one();
        if (xcUser != null) AuthEmailAlreadyRegisterException.cast();
        xcUser = lambdaQuery().eq(XcUser::getCellPhone, registerUserDTO.getCellphone()).one();
        if (xcUser != null) AuthPhoneAlreadyRegisterException.cast();
        // 4. 创建用户，保存到数据库
        xcUser = new XcUser().setId(UUID.randomUUID().toString())
                .setUserType(UserTypeConstant.USER_TYPE_STUDENT)
                .setName(registerUserDTO.getNickname())
                .setUsername(registerUserDTO.getUsername())
                .setNickName(registerUserDTO.getNickname())
                .setCellPhone(registerUserDTO.getCellphone())
                .setEmail(registerUserDTO.getEmail())
                .setPassword(passwordEncoder.encode(registerUserDTO.getPassword()))
                .setCreateTime(LocalDateTime.now())
                .setUpdateTime(LocalDateTime.now())
                .setStatus("1");
        boolean save = save(xcUser);
        if (!save) XCPlusBaseException.cast(CommonError.FAILED_INSERT_TO_DATABASE);
        // 5. 用户角色表插入数据，该接口注册的是学生角色
        XcUserRole xcUserRole = new XcUserRole().setId(UUID.randomUUID().toString())
                .setUserId(xcUser.getId())
                .setRoleId(RoleIdConstant.ROLE_ID_STUDENT) // 学生角色
                .setCreateTime(LocalDateTime.now());
        save = xcUserRoleMapper.insert(xcUserRole) > 0;
        if (!save) XCPlusBaseException.cast(CommonError.FAILED_INSERT_TO_DATABASE);
    }
}
